package com.compomics.fspike.contentprovider.webprovider;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import uk.ac.ebi.kraken.interfaces.uniprot.Keyword;
import uk.ac.ebi.kraken.interfaces.uniprot.UniProtEntry;
import uk.ac.ebi.kraken.interfaces.uniprot.description.Name;
import uk.ac.ebi.kraken.model.interpro.NameImpl;
import uk.ac.ebi.kraken.model.uniprot.UniProtEntryImpl;
import uk.ac.ebi.kraken.uuw.services.remoting.EntryIterator;
import uk.ac.ebi.kraken.uuw.services.remoting.EntryRetrievalService;
import uk.ac.ebi.kraken.uuw.services.remoting.Query;
import uk.ac.ebi.kraken.uuw.services.remoting.UniProtJAPI;
import uk.ac.ebi.kraken.uuw.services.remoting.UniProtQueryBuilder;
import uk.ac.ebi.kraken.uuw.services.remoting.UniProtQueryService;

public class UniprotContentProvider {

    /**
     *
     * @param proteinName
     * @return a map with the accessions and their sequences that are found for
     * a given protein name
     * @throws IOException
     */
    public static Map<String, String> getUniprotSpikeSequencesByTerm(String proteinName)
            throws IOException {
        Map<String, String> sequences = new HashMap();

        UniProtQueryService uniProtQueryService = UniProtJAPI.factory.getUniProtQueryService();
        Query query = UniProtQueryBuilder.buildProteinNameQuery(proteinName);
        EntryIterator<UniProtEntry> entryIterator = uniProtQueryService.getEntryIterator(query);
        for (UniProtEntry uniProtEntry : entryIterator) {
            UniProtEntryImpl tempEntry = (UniProtEntryImpl) uniProtEntry;

            String recommendedHeader = ">ct|" + uniProtEntry.getPrimaryUniProtAccession().getValue() + "|";
            StringBuilder recommendedName;
            try {
                recommendedName = new StringBuilder(tempEntry.getUniProtId().getValue());
                if (!isValidProteinName(recommendedName.toString())) {
                    recommendedName.append("");
                    for (Name anAlternativeName : tempEntry.getAlternativeNames()) {
                        NameImpl tempName = (NameImpl) anAlternativeName;
                        if (isValidProteinName(tempName.getValue())) {
                            recommendedName.append(tempName.getValue());
                            break;
                        }
                    }
                }
                if (recommendedName.toString().isEmpty()) {
                    recommendedName.append("Protein name not found (keywords :");
                    for (Keyword aKeyWord : tempEntry.getKeywords()) {
                        recommendedName.append(aKeyWord.getValue()).append(",");
                    }
                    recommendedName.setLength(recommendedName.length() - 1);
                    recommendedName.append(" )");
                }
                recommendedHeader = recommendedHeader + recommendedName;
                sequences.put(recommendedHeader, uniProtEntry.getSequence().getValue());
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }
        return sequences;
    }

    private static boolean isValidProteinName(String aName) {
        return (aName != null && !aName.toLowerCase().contains("unknown") && !aName.isEmpty());
    }

    /**
     *
     * @param uniprotAccessions list of uniprot accessions to get the sequence
     *
     * @return a map with the accessions and their sequences, for a given list
     * with uniprot accessions
     * @throws IOException
     */
    public static Map<String, String> getUniprotContaminantSequences(List<String> uniprotAccessions)
            throws IOException {
        Map<String, String> uniprotContaminantSequences = new HashMap();
        for (String uniprotAccession : uniprotAccessions) {
            uniprotContaminantSequences.put(uniprotAccession, getUniprotSpikeSequenceByAccession(uniprotAccession));
        }
        return uniprotContaminantSequences;
    }

    /**
     *
     * @param uniprotAccession
     * @return the sequence corresponding to this accession
     * @throws IOException
     */
    public static String getUniprotSpikeSequenceByAccession(String uniprotAccession) throws IOException {
        String contaminantSequence = "";
        //Create entry retrival service
        EntryRetrievalService entryRetrievalService = UniProtJAPI.factory.getEntryRetrievalService();
        //Retrieve UniProt entry by its accession number
        UniProtEntry entry = (UniProtEntry) entryRetrievalService.getUniProtEntry(uniprotAccession);
        //If entry with a given accession number is not found, entry will be equal null
        if (entry != null) {
            if (entry.getSequence() != null) {
                contaminantSequence = entry.getSequence().getValue();
            }
        } else {
            System.out.println(uniprotAccession + " could not be found...");
        }
        return contaminantSequence;
    }



}
